package com.th.apicenter.youku.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.th.apicenter.deduct.entity.ThDeduct;
import com.th.apicenter.mapper.ThDeductMapper;
import com.th.apicenter.mapper.ThYoukuDataMapper;
import com.th.apicenter.youku.dto.AdConvInfo;
import com.th.apicenter.youku.dto.ThYoukuNumDTO;
import com.th.apicenter.youku.entity.ThYoukuData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author kay
 * @date 2025/7/1
 * @TODO
 */
@Service
@Slf4j
public class YoukuService {

    @Resource
    private ThYoukuDataMapper thYoukuDataMapper;

    @Resource
    private ThDeductMapper thDeductMapper;

    public static final String APP_KEY = "31409002";
    public static final String TOKEN = "39cinhGXyD4nGoxkC6z7hdK6jR0XHfiP";

    public static final String URL = "https://missile.youku.com/api/ad/conv/v2";

    public void receive(ThYoukuData thYoukuData) {
        thYoukuDataMapper.insert(thYoukuData);
        ThDeduct thDeduct = thDeductMapper.selectOne(new QueryWrapper<ThDeduct>()
                .eq("account_id", thYoukuData.getAccountId())
                .eq("type", "youku"));
        if (null != thDeduct && thDeduct.getIsTrue() == 1) {
            Date currentTime = new Date();
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
            String date = formatter.format(currentTime);
            String startTime = date + " 00:00:00";
            String endTime = date + " 23:59:59";
            ThYoukuNumDTO thYoukuNumDTO = thYoukuDataMapper.queryNumByDate(thYoukuData.getAccountId(), startTime, endTime);
            if (thYoukuNumDTO.getPassbackNum() >= 1) {
                BigDecimal x = new BigDecimal(thYoukuNumDTO.getPassbackNum()).divide(new BigDecimal(thYoukuNumDTO.getTotal()), 2, RoundingMode.CEILING);
                BigDecimal percent = new BigDecimal(thDeduct.getPercent()).divide(new BigDecimal(100), 2, RoundingMode.CEILING);
                if (percent.doubleValue() != 0 && new BigDecimal(1).subtract(x).compareTo(percent) < 0) {
                    log.info("需要扣量，不做操作!");
                } else {
                    String result = passBackYouku(thYoukuData, thDeduct);
                    thYoukuData.setResultData(result);
                }
            } else {
                String result = passBackYouku(thYoukuData, thDeduct);
                thYoukuData.setResultData(result);
            }
            thYoukuData.setUpdateDate(new Date());
            thYoukuDataMapper.updateById(thYoukuData);
        }
    }

    public String passBackYouku(ThYoukuData thYoukuData, ThDeduct thDeduct) {
        Map<String, Object> param = new HashMap<>();
        param.put("event_type", "wake");
        param.put("deep_conv", 0);
        param.put("click_id", thYoukuData.getClickid());
        param.put("event_time", new Date().getTime());
        param.put("track_id", thYoukuData.getTrackid());
        param.put("creative_id", thYoukuData.getCreativeid());

        AdConvInfo advConvInfo = new AdConvInfo();
        advConvInfo.setAppKey(APP_KEY);
        advConvInfo.setContent(param);

        advConvInfo.setSignature(
                sign(advConvInfo.getAppKey(), TOKEN, toStr(advConvInfo.getContent())));
        String result = null;
        try {
            result = doPostEntityJSON(URL, advConvInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    public static String doPostEntityJSON(String url, Object postReq) {
        RequestConfig requestCong = RequestConfig.custom().setConnectionRequestTimeout(5000)
                .setConnectTimeout(5000).setSocketTimeout(5000).build();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestCong);
        httpPost.setEntity(new StringEntity(JSON.toJSONString(postReq), ContentType.APPLICATION_JSON));

        CloseableHttpClient httpClient = HttpClients.custom().setMaxConnTotal(100).setMaxConnPerRoute(100).setRetryHandler(
                new DefaultHttpRequestRetryHandler(0, false)).disableAutomaticRetries().build();

        CloseableHttpResponse httpResponse = null;
        try {
            httpResponse = httpClient.execute(httpPost);
            return EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
        } catch (Exception e) {
            return null;
        }
    }

    // 签名
    public static String sign(String appKey, String appSecret, String content) {
        StringBuilder keyBuilder = new StringBuilder();
        keyBuilder.append(appKey).append(content);
        return MD5(encrypt(keyBuilder.toString(), appSecret, "HmacSHA256"));
    }

    // HmacSHA256加密算法获取加密串
    public static String encrypt(String key, String appSecret, String cryptoType) {
        try {
            SecretKeySpec signingKey = getSecretKey(appSecret, cryptoType);
            Mac mac = Mac.getInstance(cryptoType);
            mac.init(signingKey);
            byte[] rawHmac = mac.doFinal(key.getBytes());
            String hexBytes = byte2hex(rawHmac);
            return hexBytes;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static SecretKeySpec getSecretKey(String appSecret, String cryptoType) {
        try {
            byte[] keyBytes = appSecret.getBytes();
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, cryptoType);
            return secretKey;
        } catch (Exception var4) {
            return null;
        }
    }

    private static String byte2hex(final byte[] b) {
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            stmp = (Integer.toHexString(b[n] & 0xFF));
            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            } else {
                hs = hs + stmp;
            }
        }
        return hs;
    }

    public static String toStr(Map<String, Object> params) {
        if (MapUtils.isEmpty(params)) {
            return null;
        }
        List<String> paramNameList = Lists.newArrayList();
        paramNameList.addAll(params.keySet());
        Collections.sort(paramNameList);
        StringBuilder builder = new StringBuilder();
        boolean first = true;
        for (String key : paramNameList) {
            if (first) {
                first = false;
            } else {
                builder.append("&");
            }
            builder.append(key).append("=");
            Object value = params.get(key);
            String valueString = "";
            if (null != value) {
                if (value instanceof Map) {
                    valueString = String.valueOf(new TreeMap<>((Map) value));
                } else if (value instanceof List) {
                    ArrayList<String> temp = new ArrayList<String>((List) value);
                    Collections.sort(temp);
                    valueString = String.valueOf(temp);
                } else {
                    valueString = String.valueOf(value);
                }
            }
            builder.append(valueString);
        }
        return builder.toString();
    }

    public static String MD5(String s) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] bytes = md.digest(s.getBytes("utf-8"));
            return toHex(bytes);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String toHex(byte[] bytes) {

        final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
        StringBuilder ret = new StringBuilder(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            ret.append(HEX_DIGITS[(bytes[i] >> 4) & 0x0f]);
            ret.append(HEX_DIGITS[bytes[i] & 0x0f]);
        }
        return ret.toString();
    }
}
